package com.guang.readandwritelock;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author lg
 * @Description 读写锁，并发读写
 *
 *  读读并发
 *  读写互斥
 *  写写互斥
 *
 *  解决性能带来的问题!!!
 *  带来重入引进的问题
 * @date 2022/10/17 14:45
 */
public class ReadWriterLockTestOne {

    /**
     * 还有公平锁和非公平锁之分
     */
    static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public static void main(String[] args) {

    }
}

// 官方给的使用案例
class CachedData {

    // 缓存数据
    Object data;

    // 缓存是否失效。默认无效
    volatile boolean cacheValid;

    final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    // 处理数据
    void processCachedData() {

        // 获取读锁
        rwl.readLock().lock();

        if (!cacheValid) {
            // 缓存失效
            // Must release read lock before acquiring write lock

            // 但是为什么需要将读锁解开，然后再次上写锁。如果相对于同一个线程来说的话，没有必要解开读锁，然后上写锁
            // 因为升级可能会导致死锁，在读写锁源码中直接拒绝了

            // 先将读锁给释放掉，然后加上写锁
            rwl.readLock().unlock();
            // 加写锁  为了保证缓存是有效的，因为可能会在写的时候存在读的情况，如果是读的话，那么就可能会存在读取得到脏数据的情况，所以需要在上面加上读锁
            rwl.writeLock().lock();
            try {
                // Recheck state because another thread might have
                // acquired write lock and changed state before we did.
                if (!cacheValid) {
                    // TODO 如果还是失效，那么需要将缓存进行更新
                    // data = ...
                    cacheValid = true;
                }
                // Downgrade by acquiring read lock before releasing write lock
                rwl.readLock().lock();
            } finally {
                rwl.writeLock().unlock(); // Unlock write, still hold read
            }
        }

        // 缓存有效
        try {
            // TODO
            // use(data);
        } finally {
            rwl.readLock().unlock();
        }
    }
}

